﻿using System;
using System.IO;
using System.Threading.Tasks;
using BulkUploadGovernanceFiles.MoveInsightToS3Buckets;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Builders;
using MongoDB.Driver.GridFS;

namespace BulkUploadGovernanceFiles
{
    public class MongoGridFSRepository
    {
        private readonly MongoDatabase _database;
        //todo: add connection string to caller name
        public MongoGridFSRepository()
        {
            var clientPlatformConnectionString = ConfigManager.GovernanceInputFile.ConnectionString; //"mongodb://localhost:27017/ClientPlatform";
            var mongoClient = new MongoClient(clientPlatformConnectionString);
            var server = mongoClient.GetServer();
            _database = server.GetDatabase(ConfigManager.GovernanceInputFile.DataBaseName);
        }
        public MongoGridFSRepository(string dataBaseName, string connectionString)
        {
            var mongoClient = new MongoClient(connectionString);
            var server = mongoClient.GetServer();
            _database = server.GetDatabase(dataBaseName);
        }


        // for testing 
        public ObjectId Write2MongoGridFs(string fullpath)
        {
            var fileInfo = _database.GridFS.Upload(fullpath, Path.GetFileName(fullpath));
            return fileInfo.Id.AsObjectId;
        }
        public void CopyFileFromMongo2Disk(ObjectId idFile, string path2Save)
        {
            _database.GridFS.Download(path2Save, Query.EQ("_id", idFile));
        }

        //small files write and read
        public Guid WriteStreamToMongoFs(string fileName, Stream content, Guid id, string contentType = null)
        {
            var fsSettings = new MongoGridFSCreateOptions()
            {
                Id = id,
                ContentType = contentType,
                ChunkSize = MongoGridFSSettings.Defaults.ChunkSize,
                UploadDate = DateTime.UtcNow
            };
            var result = _database.GridFS.Upload(content, fileName, fsSettings);
            return result.Id.AsGuid;
        }
        public Tuple<Stream, string, string> ReadStreamFromMongoFs(Guid id)
        {
            var fi = _database.GridFS.FindOneById(id);
            if (fi != null)
                return new Tuple<Stream, string, string>(fi.OpenRead(), fi.Name, fi.ContentType);
            return null;
        }
        // stream write and read
        public Tuple<Stream, Guid> NewFile(string fileName, Guid id, string contentType)
        {
            var fsSettings = new MongoGridFSCreateOptions()
            {
                Id = id,
                ContentType = contentType,
                ChunkSize = MongoGridFSSettings.Defaults.ChunkSize,
                UploadDate = DateTime.UtcNow
            };

            var fi = new MongoGridFSFileInfo(_database.GridFS, fileName, fsSettings);
            return new Tuple<Stream, Guid>(fi.Create(), fi.Id.AsGuid);
        }

        public Tuple<Stream, Guid> UpdateFile(string fileName, Guid id, Guid newid, string contentType)
        {
            //todo petre reimplement by returning stream and reset lenght
            _database.GridFS.DeleteById(id);
            return NewFile(fileName, newid, contentType);
        }

        public string ReadFileName( Guid id)
        {
            var obj = _database.GridFS.FindOneById(id);
            if (obj != null)
                return obj.Name;

            return string.Empty;
        }

        public void DeleteFile(Guid id)
        {
            var obj = _database.GridFS.FindOneById(id);
            if (obj != null)
            {
                _database.GridFS.DeleteById(BsonValue.Create(id));
            }
        }

        public void DeleteAllFiles()
        {
            var queryAll = Query.GT("length", (BsonValue)0);
            _database.GridFS.Delete(queryAll);
        }
    }
}
